/***************************************************************************
 *   Copyright (C) 2008, 2009 by MJ   *
 *   mj_dv@web.de   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

//conf_server.cpp - is a part from steamserverutil by MJ
//steamserverutil.googlecode.com

//conf_server.cpp handles the functions to configure a server

#include <iostream> //for cout and cin
#include <fstream> //for ifstream and ofstream
#include <stdlib.h> //for system()
#include <vector>

//for gettext
#include <libintl.h>
#include <locale.h>

#define _(STRING) gettext(STRING)

#include "steamserverutil.h"
#include "mani.h"
#include "sourcemod.h"
#include "metamod.h"

//to make the differance of the arrays better 
#define OFF_N 0
#define OFF_C 1

using namespace std;


void copy_maps()
{
	
	//in char param[] is saved the complete cp command
	
	cout << _("\n\nInto which server do you want to copy the maps?");

	
	int choice = choose_dialog();
	
	if(choice == -1)
		return;

	installed=false; //is set true when server is installed

	
	param = "cd " + workdir + "/";
	
	server_path(server[choice]);
	
	

	if(installed==true)
	{
		
		
		cout << _("\n\nWhere are the maps? ");
		cin >> temp;

		param += "&& cp -v " + temp + "/* maps/ ";

		system_check(system(param.c_str()));
		
		//cin.ignore();

		
	}
	
}

void edit_mapcl(int x)
{
	//x=1 to edit maplist.txt
	//x=2 to edit mapcycle.txt
	//x=3 to edit votemaplist.txt (only with mani admin plugin)





	cout << _("\n\nFrom which server do you want to edit the ");
	if(x==1)
		cout << _("maplist?");
	if(x==2)
		cout << _("mapcycle?");
	if(x==3)
		cout << _("votemaplist.txt?");


	int choice = choose_dialog();
	
	if(choice == -1)
		return;

	installed=false; //is set true when server is installed
	
	

	param = workdir + "/";
	
	if(x==3) //means votemaplist
		mani_test(server[choice]);
	else
		server_path(server[choice]);




	if(installed==true)
	{

		string mapfolder;


		
		mapfolder = param + "/maps/";

		if (x==1)
		{
			param += "/maplist.txt";
	
		}
		if(x==2)
		{
			param += "/mapcycle.txt";
	
		}
		if(x==3)
		{
			param += "/cfg/mani_admin_plugin/votemaplist.txt";
		}







		bool exit =false;
			
		while(!exit)
		{
	
			if((x !=1) && (x !=2) && x !=3)
			{
				never_happen();
				break;
			}


			if (x==1)
			{
				cout << _("\n\nHere is your current maplist: \n\n");
			}
			if(x==2)
			{
		
				cout << _("\n\nHere is your current mapcycle: \n\n");
			}
			if(x==3)
			{
				cout << _("\n\nHere is your current votemaplist: \n\n");
			}



	
			//x=1 to edit maplist.txt
			//x=2 to edit mapcycle.txt
			//x=3 to edit votemaplist.txt (only with mani admin plugin)

		
			
	
			ifstream input; //to read current *.txt
			input.open(param.c_str());

			ofstream output; //to add a new entry
			output.open(param.c_str(), ios_base::app);


			vector<string> maps;
			unsigned int i;

			i=0;

			if(input.is_open())
			{	
				while(!input.eof())
				{
					getline(input, temp);
					
					

					if(temp[0] == 10 || temp[0] == 0) //10 means new line, 0 means end of string
					{
						//nothing to do
					}
					else
					{
						maps.push_back(temp);
						cout << (i+1) << ".\t" << maps[i] << endl;
						i++;
					}
				}
			}
			else
			{
				cout << _("\nNo maps. Please add one\n");
			
			}	
			input.close();



			string map; //for case3


		
			unsigned short int choice;
			
			cout << _("\n\n1. Add a map\n");
			cout << _("2. Delete a map\n");
			cout << _("3. Copy all maps from map folder\n");
			cout << _("4. Delete all maps\n");
			cout << _("5. Back \n");
			cout << " : ";

			cin >> choice;

			cin.ignore();



	
			switch(choice)
			{
				case 1: cout << _("\n\nName of map? ");
					getline(cin, temp);
				
					output << endl << temp;
					break;

				case 2: cout << _("\n\nWhich map do you wish to delete? ");
				unsigned int choice;

				cin >> choice;
				choice--;
					
				if (choice >= i)
				{
					cout << _("\n\nThis entry does not exist!\n");
				}
				else
				{
					ofstream save_del;
					save_del.open(param.c_str());

					//iterator from begining + the choice
					maps.erase(maps.begin() + choice);

					for (int y = 0; y<maps.size(); y++)
						save_del << maps[y] << endl;
					
					save_del.close();
				}
				break;

				case 3: 
					

					map = '^'; // to avoid errors with strncmp()
					//map[1]=0;

					temp = "ls -1 " + mapfolder + " > temp.txt";

					system_check(system(temp.c_str()));

					
					{
						ifstream in_temp;
						in_temp.open("temp.txt");

						ofstream out;
						out.open(param.c_str());
						
						if(in_temp.is_open())
						{
							while(!in_temp.eof())
							{
								
								getline(in_temp, temp);
								
								
								if(!temp.compare(0, map.size()-1, map.c_str()))
								{
									continue;
								}

								if(!temp.compare("materials"))
								{
									continue;
								}
					
								if(!temp.compare("graphs"))
								{
									continue;
								}

								if(!temp.compare("soundcache"))
								{
									continue;
								}


								map.clear();

								for(int i=0; i <= temp.size(); i++)
								{
									int k = 0;
									switch(temp[i])
									{
										case '.': k=1; 
										break;
										default: map += temp[i];
										break;
									}
									if(k==1)
									{
										map += '\0'; //0 means end of string
										break;
									}
								}
								out << map << endl;
							}
						}
						else
						{
							never_happen();
							cout << _("Cannot open temp.txt");
						}

						in_temp.close();
						out.close();
					}


					
					system_check(system("rm -rf temp.txt"));

					break;

					
					case 4: 
						
					{ //otherwise we cannot create the char
						char tempi;
						cout << _("\n\nAll the maps are going to be deleted. Are you sure?(y|n) ");
						cin >> tempi;
					
	
						if(tempi=='y')
						{
							ofstream del_all;
							del_all.open(param.c_str());
							del_all.close();
						}
						break;
					}
					case 5: exit=true;
					
					break;
				
					default: cout << _("\n\nWrong choice. Try again ;)");
					break;
			}


			
			output.close(); //closing file to add a new entry
			
		}
	



	}



}



void config_servercfg()
{
	cout << _("\n\nFrom which server do you wish to edit the server.cfg?\n");
	
	int choice = choose_dialog();
	
	if(choice == -1)
		return;
	
	
	installed = false;
	
	param = workdir + "/"; //using global string here
	
	server_path(server[choice]);
	
	
	param += "cfg/server.cfg";
	
	
	
	if(installed)
	{
		bool exit = false;
	
		while(!exit)
		{
	
			ifstream in;
			in.open(param.c_str());
	
			vector<string> input[2];
			//char input[200][2][100]; //200 commands and 100 chars length
			int counter = 0;
	
			cout << _("\n\nHere is your current server.cfg: \n");
			cout << _("   \tName\t:: Command\n");
	
			if(in.is_open())
			{
	
				while(!in.eof())
				{
					
					getline(in, temp);
		
					switch(temp[0])
					{
						case '/': if(!temp.compare(0, 5, "//n: "))
								input[OFF_N].push_back(&temp[5]);
							break;
						case 0: break; //end of string
						case 10: break; //new line
						default: input[OFF_C].push_back(temp);
						cout << (counter+1) << ".\t" << input[OFF_N].at(counter) << "\t:: " << input[OFF_C].at(counter) << endl;
							 counter ++;
						break;
			
					}
		
				}
		
		
			}
			else
				cout << _("\n\nNo commands in server.cfg, please add one ;)\n\n");
	
			in.close();
	
			cout << _("\n\n1. Add command\n");
			cout << _("2. Delete a command\n");
			cout << _("3. Delete the hole list\n");
			cout << _("4. Exit\n");
			cout << " : ";
	
			cin >> choice;
			cin.ignore();
	
	
	
	
	
	
			switch(choice)
			{
		
				case 1: cout << _("\n\nCommand: ");
				{
					string command;
					getline(cin, command);
					
					
					cout << _("Name of the command: ");
					string name;
					getline(cin, name);
						
					ofstream out;
					out.open(param.c_str(), ios_base::app);
				
					out << endl << "//n: " << name;
					out << endl << command;
				
					out.close();
				}
			
			
			
			
				break;
				case 2: cout << _("\n\nWhich command do you want to delete?\n\n");
						
				cout << " : ";
				cin >> choice;
				
				choice--;


				if(choice > counter)
				{
					cout << _("\n\nThis entry does not exist!");
				}
				else
				{

					ofstream save_del;
					save_del.open(param.c_str());

					//delete command and name
					input[OFF_N].erase(input[OFF_N].begin() + choice);
					input[OFF_C].erase(input[OFF_C].begin() + choice);


					//		 name and command should be the same
					for (int i = 0;i<input[OFF_N].size();i++)
					{

						save_del << "//n: " << input[OFF_N][i] << endl;
						save_del << input[OFF_C][i] << endl;
								
					}
					save_del.close();
				}
				break;

				case 3: char temp;
				cout << _("\n\nAll commands in server.cfg are going to be deleted. Are you sure?(y|n) ");
				cin >> temp;
				

				if(temp=='y')
				{
					ofstream del_all;
					del_all.open(param.c_str());
					del_all.close();
				}
				break;
				case 4: exit=true;
				break;
				default: cout << _("\n\nTry again ;)\n");
			} 
	
		}
	
	}
	
	
}


void show_stats()
{
	cout << _("\n\nFrom which server do you wish to see the stats?\n");
	
	int choice = choose_dialog();
	
	if(choice == -1)
		return;
	
	
	param = workdir + "/"; //using global string here
	server_path(server[choice]);	
	param += "stats.txt";
	cout << _("\n\nHere are the current stats: \n\n\n");
	
	ifstream in;
	in.open(param.c_str());
	
	if(in.is_open())
	{
	
		while(!in.eof())
		{
			
			getline(in, temp);
		
			cout << temp << endl;
		}
		
		
	}
	else
		cout << _("\n\nOops there are no stats ;)\n\n");
				
	in.close();
				
	
				
	cout << _("\n\nDelete all stats?(y|n) ");
	char asd;
	cin >> asd;
	
	if(asd=='y')
	{
		cout << _("Are you sure, really delete all stats?(y|n) ");
		cin >> asd;
		
		if(asd=='y')
		{
			ofstream delete_;
			delete_.open(param.c_str());
			delete_.close();
			cout << _("\n\nDeleted succesfully!!\n\n");
		}
		
		
	}
}

void get_servername(unsigned int choice)
{
	switch(choice)
	{
		case 1: param = "css";
			break;
		case 2: param = "dods";
			break;
		case 3: param = "garrysmod";
			break;
		case 4: param = "hl2mp";
			break;
		case 5: param = "tf";
			break;
		case 6: param = "cstrike";
			break;
		case 7: param = "cscz";
			break;
		case 8: param = "dmc";
			break;
		case 9: param = "dod";
			break;
		case 10: param = "gearbox";
			break;
		case 11: param = "ricochet";
			break;
		case 12: param = "tfc";
			break;
		case 13: param = "darkmessiah";
			break;
		case 14: param = "chivalry";
			break;
		case 15: param = "diprip";
			break;
		case 16: param = "insurgency";
			break;
		case 17: param = "synergy";
			break;
		case 18: param = "zps";
			break;
		case 19: param = "esmod";
			break;
		case 20: param = "l4d";
			break;
		case 21: param = "hole";
			break;
	}
}

void set_workspace()
{
	cout << _("\n\nCurrent workspace is: ") << workdir;
	
	cout << _("\nAvailable workspaces: \n");
	
	
	
	param = home_dir + "/.steamserverutil/workdirs";
	
	ifstream in;
	
	vector<string> work;
	unsigned short int counter = 0;
	
	bool exit = false;
			
	while(!exit)
	{
		
		
		in.open(param.c_str());
		counter = 0;
		work.clear();
		
		if(in.is_open())
		{
			while(!in.eof())
			{
				getline(in, temp);
				
				
				
				if(temp[0] != 10 && temp[0] != 0) //10 means new line
				{
					work.push_back(temp);
					cout << (counter+1) << ".\t" << work[counter] << "\n";
					counter ++;	//to overwrite and ignore the new line
					
				}
			}
			
			
		}
		else
			cout << _("\nThere are no workspaces! Add one!\n");
			
		
		
		
		
		in.close();
		
		unsigned short int choice;
		
		cout << _("\n\n1. Add workspace\n");
		cout << _("2. Delete workspace\n");
		cout << _("3. Delete all workspaces\n");
		cout << _("4. Set the current standard workspace\n");
		cout << _("5. Exit\n");
		cout << " : ";
		cin >> choice;
		cin.ignore();
		
		switch (choice)
		{
			case 1: cout << _("\nPath: ");
				{
					
					getline(cin, temp);
					ofstream out;
					out.open(param.c_str(), ios_base::app);
					out << endl << temp;
					out.close();
					
					//creating the dir
					string _temp = "mkdir " + temp;
					system_check(system(_temp.c_str()));
				}
				break;
		
		
			case 2: cout << _("\n\nWhich workspace do you want do delete? ");
				cin >> choice;
				
				choice--;
			
				if(choice >= counter)
				{
					cout << _("\nThis entry does not exist!\n\n");
				}
				else
				{
			
					ofstream save_del;
					save_del.open(param.c_str());
			
			
					work.erase(work.begin() + choice);
			
			
					for (int i = 0;i<work.size();i++)
						save_del << work[i] << endl;
						
									
					
					save_del.close();
				}
				break;
			case 3: char temp;
				cout << _("\n\nAll workspaces are going to be deleted. Are you sure?(y|n) ");
				cin >> temp;
							
			
				if(temp=='y')
				{
					ofstream del_all;
					del_all.open(param.c_str());
					del_all.close();
				}
				break;
			case 4:
				cout << _("\n\nWhich workspace do you want to set as the current wokspace? ");
				cin >> choice;
			
				choice--;
		
				if(choice >= counter)
				{
					cout << _("\nThis entry does not exist!\n\n");
				}
				else
				{
					cout << _("Setting \"") << work[choice] << _("\" to standard");
					
					//extra variable is needed here
					string params;
					params = home_dir + "/.steamserverutil/workdir";
					
					ofstream save(params.c_str());
					save << work[choice];
					save.close();
					
					cout << _("\n\nPlease restart steamserverutil now, to make the changes effect!\n\n");
				}
				
				
				break;
			case 5: exit=true;
				break;
			default: cout << _("\n\nTry again;)\n\n");
			break;
		}
	}
}


void backup()
{
	cout << _("\n\nWhich server do you wish to backup?\n");
	
	is_installed();
	cout << i << _("\tHole content\n");
	cout << ++i << _(".\tExit\n");
	cout << " : ";
	unsigned short int choice;
	cin >> choice;
	
	if(choice > i || choice == i)
		return;
	
	i--; // to remove exit clause
	
	server[i] = 21; //to get "hole" returned from get_servername
	get_servername(server[choice]);
	
	//getting name of server...
	string name;
	name = param;
	
	//writing the temporary file, needed to recognize the archive
	param = workdir + "/ssu_cur_servername.txt";
	
	ofstream out_name(param.c_str());
	
	out_name << name << endl;	
	out_name << "# steamserverutil " << _version << endl;
	out_name << "# This tar archive is a backup file of steamserverutil (steamserverutil.googlecode.com)\n";
	out_name << "# Please do not make any changes on this archive !\n";
	out_name.close();
	
	
	param = "cd " + workdir  + " && tar -cf ../backup_steamserverutil_" + name + ".tar ssu_cur_servername.txt ";
	
	if(server[choice] != 21)
		server_path(server[choice]);
	else
		param += "servers_source/ servers_hl1/ installed_servers hldsupdatetool.bin steam favorites ";
	
	
	
	cout << _("Creating backup_steamserverutil.tar... ");
	cout << flush;
	
	system_check(system(param.c_str()));
	
	
	cout << _("Success\n(Backup saved to workspace folder)\n");
	
	
}

void restore_backup()
{
	cout << _("\nAttention: The existing data of the specific server will be overwritten by the backup\n");
	cout << _("\nWhere is the backup file (*.tar)? ");
	
	bool valid = false;
	bool restore_fav = false; //bool which is set to true, when we need to restore a favorites file
	string path;
	cin.ignore();
	getline(cin, path);
	
	param = "tar --list -f " + path + " > temp.txt";
	
	cout << _("\nAnalyzing the archive, this may take a while!\n\n");
	cout << flush;
	system_check(system(param.c_str()));
	
	
	ifstream in("temp.txt");
	
	if(in.is_open())
	{
		while(!in.eof())
		{
			
			
			getline(in, temp);
			if(!temp.compare("favorites"))
				restore_fav = true;
			if(!temp.compare("ssu_cur_servername.txt"))
				valid = true;
		}
	}
	else
	{
		cerr << _("\nSomething went wrong with checking the validity of the archive!\nMaybe wrong file Path?\n");
		return;
	}
	
	in.close();
	
	system_check(system("rm -rf temp.txt"));
	
	if(!valid)
	{
		cout << _("\n\nThis seems not to be a valid backup file!\nAborting...\n\n");
		return;
	}
	
	
	
	param = "cd " + workdir + " && tar -xf " + path;
	
	cout << _("Extracting archive...\n");
	cout << flush;
	system_check(system(param.c_str()));
	
	
	cout << _("\nAdding restored server to installed_servers file\n");
	
	param = workdir + "/installed_servers";
	
	//using path[] to open ssu_cur_servername.txt now
	
	path = workdir + "/ssu_cur_servername.txt";
	
	
	ofstream out(param.c_str(), ios_base::app);
	
	
	if(!restore_fav) //if we have to restore favorites, we do not need to write the servers in is_installed
	{
		in.open(path.c_str());
		
		
		while(!in.eof())
		{
			getline(in, temp);
			
			if(temp[0] == '#')
				break;
			//else:
			out << temp;
		}
		
		
	}
	
	out.close();
	in.close();
	
	
	
	if(restore_fav)
	{
		cout << _("\nConverting backuped favorites to new workspace.\n\n");
		
		path = workdir + "/favorites";
		
		in.open(path.c_str());
		
		
		
		vector<string> input[2];
		int j = -1;
		
		if(in.is_open())
		{
	
		
			while(!in.eof())
			{
	
				
				
				getline(in, temp);
	
				switch(temp[0])
				{
					case 'n': if(temp[1] == ':')
					{
						j++;
						input[OFF_N].push_back(&(temp[3]));
							
					}
					else
						cout << _("Your .favorites is incorrupt, cannot understand: ") << temp << _("\nIgnoring...\n");
					break;
					case 'c': if(temp[1] == ':')
					{
						input[OFF_C].push_back( &(temp[3]));
					}
					else
						cout << _("Your .favorites is incorrupt, cannot understand: ") << temp << _("\nIgnoring...\n");
					break;
					default: if(temp[0] == 10 || temp[0]== 0) //10 means new line 0 means end of string
					{
							//nothing to do
					}
					else
						cout << _("Your .favorites is incorrupt, cannot understand: ") << temp << _("\nIgnoring...\n");
					break;
				}
				
				
			}
		
				
				
		}
		else
		{
			cout << _("You have no favorites, please add one!\n\n");
		}
		
		in.close();
		
		out.open(path.c_str());
		
		//now all favorites are saved in input
		//now checking if path is correct if yes write the hole file new!
		//otherwise change it and write the file then!
		
		for (int i = 0;i<=j;i++)
		{
			
			
			//		ignore the "cd "
			if( input[OFF_C][i].compare( 3, workdir.size(), workdir.c_str() ) )
			{
				temp = "cd " + workdir;
				
				int index = input[OFF_C][i].find("/servers_source");
				
				if(index == -1)
					index = input[OFF_C][i].find("/servers_h1");
				if(index == -1)
					index = input[OFF_C][i].find("/servers_darkmessiah");
				
				temp += input[OFF_C][i].substr(index);
				
				//copy temp to input
				
				input[OFF_C][i] = temp;
			}
			
			out << "n: " << input[OFF_N][i] << endl;
			out << "c: " << input[OFF_C][i] << endl;
			
				
		}
		out.close();
		
		cout << _("\nSuccess!\n\n");
	}
}


//here you can configure servers
void config_server()
{
	bool exit=false;

	while(!exit)
	{
		unsigned short int choice;
		cout << _("\n\n1. Copy maps into server\n");
		cout << _("2. Edit maplist\n");
		cout << _("3. Edit mapcylce\n");
		cout << _("4. Edit server.cfg\n");
		cout << _("5. Show stats\n");
		cout << _("6. Configure mani admin plugin\n");
		cout << _("7. Configure metamod\n");
		cout << _("8. Configure sourcemod\n");
		cout << _("9. Change workspace(s)\n");
		cout << _("10. Backup\n");
		cout << _("11. Restore a Backup\n");
		cout << _("12. Exit to main menu\n");
		cout << " : ";
		cin  >> choice;	

		switch(choice)
		{
			case 1: copy_maps();
			break;
			case 2: edit_mapcl(1); //1 means edit maplist.txt
			break;
			case 3: edit_mapcl(2); //2 means edit mapcycle.txt
			break;
			case 4: config_servercfg();
			break;
			case 5: show_stats();
			break;
			case 6:	config_mani();
			break;
			case 7: config_metamod();
			break;
			case 8: config_sourcemod();
			break;
			case 9: set_workspace();
			break;
			case 10: backup();
			break;
			case 11: restore_backup();
			break;
			case 12: exit=true;
			break;
			default: cout << _("\n\nWrong choice. Try again;)");
			break;
		}
	}
}
